5. Indexing JOIN Criteria
Next, you want to retrieve
all the orders that contain a certain product. Let's query the
SalesOrderDetail table to identify the records. Execute the following
code sample. The resulting plan is shown in Figure 9.
SELECT sod.SalesOrderID,sod.SalesOrderDetailID,p.Name,sod.OrderQty
FROM apWriter.SalesOrderDetail sod JOIN apWriter.Product p
ON sod.ProductId = p.ProductId
WHERE p.ProductId = 843
As you review the
execution plan, you should see that the bulk of the cost of the query
comes from the clustered index scan on the SalesOrderDetail table. If
you follow some of the tips discussed in this chapter, then you need to
create a nonclustered index on the foreign key within the
SalesOrderDetail table.
Since you are also querying
the data for the order quantity, you may want to cover the query and
include the OrderQty column in the index creation. For demo purposes, Listing 5
creates two indexes: a nonclustered index on just the product ID and a
nonclustered index on the product ID that includes the OrderQty column
as well.
Example 5. SQL Code That Creates Nonclustered Indexes and Queries Multiple Tables
CREATE NONCLUSTERED INDEX ix_ProductId ON apWriter.SalesOrderDetail(ProductId)
CREATE NONCLUSTERED INDEX ix_ProductIdInclude ON apWriter.SalesOrderDetail(ProductId) INCLUDE (OrderQty)
SELECT sod.SalesOrderID,sod.SalesOrderDetailID,p.Name,sod.OrderQty FROM AdventureWorks2008.apWriter.SalesOrderDetail sod WITH (index(ix_ProductIdInclude)) JOIN AdventureWorks2008.apWriter.Product p ON sod.ProductId = p.ProductId WHERE p.ProductId = 843
SELECT sod.SalesOrderID,sod.SalesOrderDetailID,p.Name,sod.OrderQty FROM apWriter.SalesOrderDetail sod with(index(ix_ProductId)) JOIN apWriter.Product p on sod.ProductId = p.ProductId WHERE p.ProductId = 843
|
After creating the indexes, Listing 5 executes two queries to demonstrate the impact of those indexes. Figure 10 shows the resulting execution plans.
The execution plan in Figure 10
shows the nonclustered index with the include columns, or the first
query in the execution plan. The query cost is less because the index
covers the query. Pop quiz: Why don't you have to include the SalesOrderId
in the index in order to cover the query? Keep in mind that
nonclustered indexes contain the clustered index key on the
intermediate and leaf level pages. So the query optimizers already have
those values and no lookup is required.